package com.alipay.rebate.shop.service.customer.impl;

import com.alipay.rebate.shop.constants.StatusCode;
import com.alipay.rebate.shop.constants.UserIncomeConstant;
import com.alipay.rebate.shop.dao.mapper.SignInAwardMapper;
import com.alipay.rebate.shop.dao.mapper.SignInRecordMapper;
import com.alipay.rebate.shop.dao.mapper.UserIncomeMapper;
import com.alipay.rebate.shop.dao.mapper.UserMapper;
import com.alipay.rebate.shop.exceptoin.BusinessException;
import com.alipay.rebate.shop.model.SignInAward;
import com.alipay.rebate.shop.model.SignInRecord;
import com.alipay.rebate.shop.model.SignInSettings;
import com.alipay.rebate.shop.model.UserIncome;
import com.alipay.rebate.shop.pojo.user.customer.SignInReq;
import com.alipay.rebate.shop.service.customer.CustomerSignInRecordService;
import com.alipay.rebate.shop.utils.DateUtil;
import com.alipay.rebate.shop.utils.DecimalUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Random;


/**
 * Created by CodeGenerator on 2019/09/21.
 */
@Service
@Transactional
public class CustomerSignInRecordServiceImpl implements CustomerSignInRecordService {

    private Logger logger = LoggerFactory.getLogger(CustomerSignInRecordServiceImpl.class);
    @Resource
    private SignInRecordMapper signInRecordMapper;
    @Resource
    private SignInAwardMapper signInAwardMapper;
    @Resource
    private UserIncomeMapper userIncomeMapper;
    @Resource
    private UserMapper userMapper;

    @Override
    public Integer signIn(Long userId, SignInReq req) throws ParseException {

        SignInRecord todayRecord = signInRecordMapper.selectToDayRecord(userId);
        if(todayRecord != null){
            throw  new BusinessException("当天已签到", StatusCode.SIGN_IN_ERROR);
        }
        // 获取签到配置
        // TODO
        SignInSettings signInSettings = null;
        logger.debug("SignInSettings is : {}",signInSettings);
        String strDateFormat = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
//        Date date = sdf.parse(req.getSignInTime());
        Date date = new Date();
        logger.debug("Date is :{}",date);
        // 保存签到记录
        SignInRecord signInRecord = buildSignInRecord(signInSettings,userId,date,req);
        signInRecordMapper.insertSelective(signInRecord);
        logger.debug("SignInRecord is : {}",signInRecord);
        // 查询昨天是否有签到
        SignInRecord yesterDayRecord = signInRecordMapper.selectYesterDayRecord(userId,sdf.format(date));
//        SignInRecord yesterDayRecord = signInRecordMapper.selectYesterDayRecord(userId,req.getSignInTime());
        logger.debug("yesterDayRecord is : {}",yesterDayRecord);
        SignInAward signInAward = signInAwardMapper.selectByUserId(userId);
        logger.debug("SignInAward is: {}",signInAward);
        // 如果昨天没有签到,那么开启新一轮签到
        if(yesterDayRecord == null){
            logger.debug("no yesterDayRecord");
            // 如果数据库没有记录, 那么新插入
            SignInAward nSignInAward = new SignInAward();
            nSignInAward.setUserId(userId);
            nSignInAward.setNewlySignInTime(signInRecord.getSignInTime());
            nSignInAward.setSignInDays(1);
            nSignInAward.setTotalAwardMoney(signInRecord.getEstimateMoney());
            nSignInAward.setTotalAwardIntegral(signInRecord.getEstimateIntegral());
            // 如果数据库没有记录, 那么新插入
            if(signInAward == null){
                logger.debug("not signInAward , nSignInAward is : {}",nSignInAward);
                signInAwardMapper.insertSelective(nSignInAward);
            }else{
                logger.debug("have signInAward , nSignInAward is : {}",nSignInAward);
                nSignInAward.setId(signInAward.getId());
                signInAwardMapper.updateByPrimaryKeySelective(nSignInAward);
            }
        }else{// 否则, 更新签到奖励表信息
            logger.debug("have yesterDayRecord");
            SignInAward nSignInAward = new SignInAward();
            nSignInAward.setId(signInAward.getId());
            // 如果上一轮签到已经到了七天,那么开启新一轮签到
            if(signInAward.getSignInDays() == 7){
                logger.debug("last award done , start next period");
                nSignInAward.setSignInDays(1);
                nSignInAward.setNewlySignInTime(signInRecord.getSignInTime());
                nSignInAward.setTotalAwardMoney(signInRecord.getEstimateMoney());
                nSignInAward.setTotalAwardIntegral(signInRecord.getEstimateIntegral());
                signInAwardMapper.updateByPrimaryKeySelective(nSignInAward);
            }else{
                logger.debug("current period");
                nSignInAward.setSignInDays(signInAward.getSignInDays() + 1);
                BigDecimal totalMoney = signInAward.getTotalAwardMoney().
                    add(signInRecord.getEstimateMoney());
                int totalIntegral = signInAward.getTotalAwardIntegral()
                    + signInRecord.getEstimateIntegral();
                nSignInAward.setTotalAwardMoney(totalMoney);
                nSignInAward.setTotalAwardIntegral(totalIntegral);
                signInAwardMapper.updateByPrimaryKeySelective(nSignInAward);
                // 如果今天是第七天, 那么奖励给用户 -- 连续七天不再额外奖励
//                if(nSignInAward.getSignInDays() == 7){
//                    logger.debug("reach 7 day, award to user");
//                    Long integral = Long.valueOf(nSignInAward.getTotalAwardIntegral());
//                    BigDecimal money = nSignInAward.getTotalAwardMoney();
//                    // 增加用户虚拟币
//                    awardUser(signInSettings,integral,money,userId);
//                    // 更新最近七天内签到记录所得的奖励
//                    updateMoneyAndIntegralToEstimate(date,userId);
//                    // 添加用户收益记录
//                    addUserIncome(money,signInSettings,integral,userId);
//                }
            }
        }

        return 1;
    }

    private void awardUser(SignInSettings signInSettings,Long integral,BigDecimal money,Long userId){
        // 金额奖励
        if(signInSettings.getAwardType() == 1){
            userMapper.plusOrReductVirtualMoney(null,integral,money,userId);
        }
        // 集分宝奖励
        if(signInSettings.getAwardType() == 2){
            Long uit = money.multiply(new BigDecimal(100))
                .longValue();
            userMapper.plusOrReductVirtualMoney(uit,integral,null,userId);
        }
        // 积分奖励
        if(signInSettings.getAwardType() == 3){
            userMapper.plusOrReductVirtualMoney(null,integral,money ,userId);
        }
    }

    private void updateMoneyAndIntegralToEstimate(Date date, Long userId){
        // 更新最近七天内签到记录所得的奖励
        LocalDateTime localDateTime = DateUtil.transferDateToLocalDateTime(date);
        LocalDate localDate = localDateTime.toLocalDate();
        localDate = localDate.minusDays(6L);
        String startTime = DateUtil.doGetTimeStrByDay(localDate);
        localDate = localDate.plusDays(7L);
        String endTime = DateUtil.doGetTimeStrByDay(localDate);
        logger.debug("startTime and endTime is :{},{}",startTime,endTime);
        signInRecordMapper.upateMoneyAndIntegralByUserId(userId,startTime,endTime);
    }

    private void addUserIncome(BigDecimal money,SignInSettings signInSettings,Long integral,Long userId){
        if(DecimalUtil.biggerThanZero(money)){
            UserIncome userIncome = buildUserIncome(money,
                signInSettings.getAwardType(),null,userId);
            userIncomeMapper.insertSelective(userIncome);
        }
        if(integral >0 ){
            UserIncome userIncome = buildUserIncome(null,
                UserIncomeConstant.IT_AWARD_TYPE,integral,userId);
            userIncomeMapper.insertSelective(userIncome);
        }
    }

    private UserIncome buildUserIncome(
        BigDecimal totalMoney,
        Integer awardType,
        Long integral,
        Long userId){
        UserIncome userIncome = new UserIncome();
        userIncome.setMoney(totalMoney);
        userIncome.setType(UserIncomeConstant.SIGN_IN_AWAED_TYPE);
        userIncome.setAwardType(awardType);
        String now = DateUtil.getNowStr();
        userIncome.setCreateTime(now);
        userIncome.setUpdateTime(now);
        userIncome.setUserId(userId);
        userIncome.setIntgeralNum(integral);
        userIncome.setStatus(UserIncomeConstant.IS_PAID);
        return userIncome;
    }

    private SignInRecord buildSignInRecord(SignInSettings signInSettings, Long userId,Date date,SignInReq req){
        SignInRecord signInRecord = new SignInRecord();
        signInRecord.setAwardType(signInSettings.getAwardType());
        signInRecord.setSignInTime(date);
        signInRecord.setUserId(userId);
        int num = estimateNum(signInSettings, req);
        // 奖励金额
        if(signInSettings.getAwardType() == 1){
            signInRecord.setEstimateMoney(new BigDecimal(num));
            signInRecord.setEstimateIntegral(0);
        }
        // 集分宝(集分宝 除 100 得金钱)
        if(signInSettings.getAwardType() == 2){
            BigDecimal money = DecimalUtil.convertUitToMoney(Long.valueOf(num));
            signInRecord.setEstimateMoney(money);
            signInRecord.setEstimateIntegral(0);
        }
        // 奖励积分
        if(signInSettings.getAwardType() == 3){
            signInRecord.setEstimateIntegral(num);
            signInRecord.setEstimateMoney(new BigDecimal(0));
        }
        signInRecord.setMoney(new BigDecimal(0));
        signInRecord.setIntegral(0);
        return signInRecord;
    }

    private int estimateNum(SignInSettings signInSettings,SignInReq req){
        // 固定式
        if(signInSettings.getAwardForm() == 1){
            return getFixMoney(signInSettings,req);
        }
        // 随机式
        if(signInSettings.getAwardForm() == 2){
            return getRandomMoney(signInSettings,req);
        }
        return 0;
    }

    private int getFixMoney(SignInSettings signInSettings,SignInReq req){
        int num = req.getNum();
        if(num != signInSettings.getFixAwardNum()){
            num = signInSettings.getFixAwardNum();
        }
        return num;
    }

    private int getRandomMoney(SignInSettings signInSettings,SignInReq req){
        Integer minNum = signInSettings.getMinAwardNum();
        Integer maxNum = signInSettings.getMaxAwardNum();
        int randomNum = req.getNum();
        if(! ((req.getNum() > minNum) && req.getNum() < maxNum) ){
            Random random = new Random();
            randomNum = random.nextInt(maxNum) % (maxNum - minNum + 1) + minNum;
        }
        return randomNum;
    }
}
